package top.bulk.delay.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import top.bulk.delay.entity.OrderEntity;
import top.bulk.delay.mapper.OrderMapper;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 轮询数据库实现延迟效果
 *
 * @author 散装java
 * @date 2024-08-13
 */
@Component
@Slf4j
public class PollingDbDelayHandler implements DelayHandler<OrderEntity> {
    @Resource
    private OrderMapper orderMapper;
    /**
     * 价格开关控制一下，方便测试
     */
    public static final AtomicBoolean POLLING = new AtomicBoolean(false);

    @Override
    public void handle(OrderEntity orderEntity, Integer second) {
        POLLING.set(true);
    }

    /**
     * 每秒钟执行一次
     * 注意，实际项目建议使用分布式任务调度框架，如：xxl-job
     * 注意方法执行时候的线程安全问题
     */
    @Scheduled(fixedDelay = 1000)
    public void polling() {
        if (!POLLING.get()) {
            return;
        }
        Integer limit = 100;

        // 实际开发中，要考虑扫表效率，更新现成安全等问题
        List<OrderEntity> list = orderMapper.queryCloseByTime(LocalDateTime.now().minusSeconds(DELAY_TIME), limit);

        list.forEach(orderEntity -> {
            if (orderEntity.canClose(DELAY_TIME)) {
                orderMapper.closeOrder(orderEntity.getId());
                log.info("订单 {} 已关闭", orderEntity.getOrderNo());
            }
        });

        // 继续查询其他的
        if (list.size() == 100) {
            polling();
        }
    }

}
